
import wx

import ab_ids as ai
import ab_plugins
import ab_utils
import ab_object

import ab_config as ac

from ab_field import AtrField
from ab_object_disp import ObjectDisp
from ab_statusbar import StatusBar


class TreeViewerCtrl(wx.TreeCtrl):
    def __init__(self, container, parent, app, title, opaque):
        self.app = app
        self.parent = parent

        self.title = title
        self.opaque = opaque

        self.app.debug('<TreeViewerCtrl.__init__> Enter')

        wx.TreeCtrl.__init__(self, container, -1,
                             wx.DefaultPosition, wx.DefaultSize)

        self.plx = self.app.readKey(ai.CfgParaPlxObject)
        self.update()

        # bind events
        self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
        self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTreeSelChanged)

        self.app.debug('<TreeViewerCtrl.__init__> Exit')

    def createTree(self, parent, objectp, level=0):
        if level >= self.app.readKey(ai.CfgParaTreeIgnoredLevel):
            self.AppendItem(
                parent, 'Ignore to display according to settings ...')
            
            return

        objs = objectp.extract()
        for obj in objs:
            objdisp = ObjectDisp(self.app, obj)
            # set the string
            child = self.AppendItem(parent, objdisp.getString())
            # set the treeId to the object field
            obj.update(opaque=child)
            self.SetPyData(child, obj)
            if obj.extractable() and obj.hasChildren():
                self.createTree(child, obj, level + 1)

    def update(self):
        self.app.debug('<TreeViewerCtrl.initTree> Enter')
        if self.opaque is not None and self.opaque.extractable():
            self.DeleteAllItems()
            self.root = self.AddRoot(self.title)

            self.SetPyData(self.root, self.opaque)
            # create the the tree content
            self.createTree(self.root, self.opaque)
            self.opaque.update(opaque=self.root)
            self.Expand(self.root)

        self.app.debug('<TreeViewerCtrl.initTree> Exit')

    def setSelection(self, section):
        if section is not None:
            # build up the object find  mode
            search_mode = self.app.readKey(ai.CfgParaTreeMatchMode) \
                & self.opaque.MatchMask
            if self.app.readKey(ai.CfgParaTreeAllMatches):
                search_mode |= self.opaque.MatchAll

            # handle the first field only
            sect = section[0]
            # TODO: adjust to use AtrField for the selections
            if not isinstance(sect, AtrField):
                sect = AtrField(sect[0], sect[1])
            obj = self.opaque.findWithField(sect, search_mode)
            if obj is not None:
                item = obj.extract('Q')
                self.SelectItem(item, True)

    def OnRightDown(self, event):
        menu = wx.Menu()

        menu.Append(ai.id_OpenWithSegment, 'Open in New Window')
        submenu = wx.Menu()
        submenu.Append(ai.id_SaveNode_Binary, 'Save as &binary')
        submenu.Append(ai.id_SaveNode_Hex, 'Save as &hexademical')
        menu.AppendMenu(ai.id_Save_Node, 'Save Node', submenu)
        menu.AppendSeparator()
        submenu = wx.Menu()
        submenu.Append(ai.id_Copy, 'Copy Field')
        submenu.Append(ai.id_Copy_Subject, 'Copy Subject')
        submenu.Append(ai.id_Copy_Description, 'Copy Description')
        submenu.Append(ai.id_Copy_Selection, 'Copy Selection')
        menu.AppendMenu(-1, 'Copy', submenu)
        menu.AppendSeparator()
        menu.Append(ai.id_Expand, '&Expand')
        menu.Append(ai.id_ExpandAll, 'Expand &All')
        menu.Append(ai.id_ExpandChildren, 'Expand Child&ren')
        menu.AppendSeparator()
        menu.Append(ai.id_Collapse, '&Collapse')
        menu.Append(ai.id_CollapseAll, 'C&ollapse All')
        # add the menu only with the plug-in enabled
        if self.plx.getInstance('AOF') is not None:
            menu.AppendSeparator()
            menu.Append(ai.id_ExportNode, 'Export &Node')
            menu.Append(ai.id_ExportTree, 'Export &Tree')
            menu.Append(ai.id_ExportWithLevel, 'E&xport...')

        # show the menu only in the developer method
        if self.app.readKey(ai.CfgParaDeveloperMethod):
            menu.AppendSeparator()
            menu.Append(ai.id_ExportJson, 'Export tree in Json')

        # formattors
        fmt_list = self.plx.getPlxList(ab_plugins.PlxTpFormatter)
        if len(fmt_list):
            submenu = wx.Menu()
            idmgr = self.app.getWindow().getIdsManager()
            for plx_name in fmt_list:
                submenu.Append(idmgr.getParsedIdWithPlx(plx_name), plx_name)

            menu.AppendSeparator()
            menu.AppendMenu(ai.id_ParseWith, 'Parsed With', submenu)

        self.PopupMenu(menu)

    def OnTreeSelChanged(self, event):
        obj = self.GetPyData(event.GetItem())
        if obj is not None:
            # set the highlight
            self.parent.setSelection(obj.extract('F'), self)
            # set the plug-in name
            plxname = obj.extract('p')
            if plxname is not None and len(plxname) > 0:
                self.parent.updateStatus(StatusBar.SHORTNAME2, state=plxname)
